package com.sugo.seckill.web.order;

import com.sugo.seckill.http.HttpResult;
import com.sugo.seckill.http.HttpStatus;
import com.sugo.seckill.order.service.SeckillOrderService;
import com.sugo.seckill.pojo.FrontUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * controller
 * @author Administrator
 *
 */
@RestController
@RequestMapping("/seckill")
public class SeckillOrderController {

	@Autowired
	private SeckillOrderService seckillOrderService;

	/**
	 * 方式1-1：秒杀下单，不使用任何锁，会出现超卖的现象
	 * @author hubin
	 * @date 2020/6/10 17:31
	 */
	@GetMapping(value = "/startSubmitOrder/{seckillId}")
	public HttpResult submitOrder(@PathVariable Long seckillId,HttpServletRequest request){

		String token = request.getHeader("Authorization");
		//判断
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}
		//单体架构，用户数据从当前session中获取
		FrontUser frontUser = seckillOrderService.getUserInfoFromRedis(token);
		//判断用户是否登录
		if(frontUser == null){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}
		//没有开启任何多线程下单
		return seckillOrderService.startSubmitOrder(seckillId, frontUser.getId() + "");

	}


	/**
	 * 方式1-2：秒杀下单（多线程的方式），不使用任何锁，会出现超卖的现象
	 * @author hubin
	 * @date 2020/6/10 17:31
	 */
	@GetMapping(value = "/submitOrderMul/{seckillId}")
	public HttpResult submitOrderMultiThread(@PathVariable Long seckillId,HttpServletRequest request){

		String token = request.getHeader("Authorization");
		//判断用户身份信息，是否合法
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//单体架构，用户数据从当前session中获取
		FrontUser frontUser = seckillOrderService.getUserInfoFromRedis(token);

		//判断用户是否登录
		if(frontUser == null){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}
		//使用了多线程的方式下单
		return seckillOrderService.startSubmitOrderMultiThread(seckillId, frontUser.getId() + "");

	}


	/**
	 * 方式2-1：秒杀下单，程序锁，防止出现超卖的现象
	 * @author hubin
	 * @date 2020/6/10 17:31
	 */
	@GetMapping(value = "/startSubmitOrderByReentrantLock/{seckillId}")
	public HttpResult startSubmitOrderByReentrantLock(@PathVariable Long seckillId,HttpServletRequest request){

		String token = request.getHeader("Authorization");
		//判断用户身份信息，是否合法
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}
		//单体架构，用户数据从当前session中获取
		FrontUser frontUser = seckillOrderService.getUserInfoFromRedis(token);
		//判断用户是否登录
		if(frontUser == null){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}
		//使用程序锁方式进行下单
		return seckillOrderService.startSubmitOrderByReentrantLock(seckillId,frontUser.getId()+"");
	}


	/**
	 * 方式3-1：秒杀下单，AOP锁，防止出现超卖的现象
	 * @author hubin
	 * @date 2020/6/10 17:31
	 */
	@GetMapping(value = "/startSubmitOrderByAOPLock/{seckillId}")
	public HttpResult startSubmitOrderByAopLock(@PathVariable Long seckillId,HttpServletRequest request){

		String token = request.getHeader("Authorization");
		//判断用户身份信息，是否合法
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//单体架构，用户数据从当前session中获取
		FrontUser frontUser = seckillOrderService.getUserInfoFromRedis(token);

		//判断用户是否登录
		if(frontUser == null){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//使用aop锁方式进行下单
		return seckillOrderService.startSubmitOrderByAOPLock(seckillId,frontUser.getId()+"");

	}


	/**
	 *  方式3-1：秒杀下单，blockingQueue队列，防止出现超卖的现象
	 * @author hubin
	 * @date 2020/6/10 17:31
	 */
	@GetMapping(value = "/startSubmitOrderByBlockingQueue/{seckillId}")
	public HttpResult startSubmitOrderByBlockingQueue(@PathVariable Long seckillId,HttpServletRequest request){

		String token = request.getHeader("Authorization");
		//判断用户身份信息，是否合法
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//单体架构，用户数据从当前session中获取
		FrontUser frontUser = seckillOrderService.getUserInfoFromRedis(token);
		//判断用户是否登录
		if(frontUser == null){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}
		//使用队列术方式，进行下单
		return seckillOrderService.startSubmitOrderByBlockingQueue(seckillId,frontUser.getId()+"");

	}


	/**
	 *  5-1 使用数据库悲观锁控制库存
	 * @author hubin
	 * @date 2020/6/10 17:31
	 */
	@GetMapping(value = "/startSubmitOrderBySQLLock/{seckillId}")
	public HttpResult startSubmitOrderBySqlLock(@PathVariable Long seckillId,HttpServletRequest request){

		String token = request.getHeader("Authorization");
		//判断用户身份信息，是否合法
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//单体架构，用户数据从当前session中获取
		FrontUser frontUser = seckillOrderService.getUserInfoFromRedis(token);

		//判断用户是否登录
		if(frontUser == null){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//使用数据库悲观锁，进行下单
		return seckillOrderService.startSubmitOrderBySQLPessimismLock(seckillId,frontUser.getId()+"");

	}


	/**
	 * 5-3 使用数据库乐观锁控制库存
	 * @author hubin
	 * @date 2020/6/10 17:31
	 */
	@GetMapping(value = "/startSubmitOrderBySQLLock3/{seckillId}")
	public HttpResult startSubmitOrderBySqlLock3(@PathVariable Long seckillId,HttpServletRequest request){

		String token = request.getHeader("Authorization");
		//判断用户身份信息，是否合法
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//单体架构，用户数据从当前session中获取
		FrontUser frontUser = seckillOrderService.getUserInfoFromRedis(token);

		//判断用户是否登录
		if(frontUser == null){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//使用数据库乐观锁，进行下单
		return seckillOrderService.startSubmitOrderBySQLOptimismLock(seckillId,frontUser.getId()+"");

	}

	/**
	 * 6-1 使用redis分布式锁进行下单
	 * @author hubin
	 * @date 2020/6/10 17:31
	 */
	@GetMapping(value = "/startSubmitOrderByRedissonLock/{seckillId}")
	public HttpResult startSubmitOrderByRedissonLock(@PathVariable Long seckillId,HttpServletRequest request){

		String token = request.getHeader("Authorization");
		//判断用户身份信息，是否合法
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//单体架构，用户数据从当前session中获取
		FrontUser frontUser = seckillOrderService.getUserInfoFromRedis(token);

		//判断用户是否登录
		if(frontUser == null){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		// 使用redis分布式锁进行下单，进行下单
		return seckillOrderService.startSubmitOrderByRedissonLock(seckillId,frontUser.getId()+"");

	}

	/**
	 *  7-1 使用redisson分布式锁方案控制库存，实现下单
	 * @author hubin
	 * @date 2020/9/5 20:48
	 */
	@GetMapping(value = "/startSubmitOrderByZookeeperLock/{seckillId}")
	public HttpResult startSubmitOrderByZookeeperLock(@PathVariable Long seckillId,HttpServletRequest request){

		String token = request.getHeader("Authorization");
		//判断用户身份信息，是否合法
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		//单体架构，用户数据从当前session中获取
		FrontUser frontUser = seckillOrderService.getUserInfoFromRedis(token);

		//判断用户是否登录
		if(frontUser == null){
			return HttpResult.error(HttpStatus.SC_FORBIDDEN,"先登录，才能抢购哦!");
		}

		// 使用zookeeper分布式锁进行下单，进行下单
		return seckillOrderService.startSubmitOrderByZookeeperLock(seckillId,"15");

	}

	/**
	 *  获取时间
	 * @author hubin
	 * @date 2020/6/10 16:19
	 */
	@RequestMapping("/submitOrder/times")
	public HttpResult getConcurrentTime(){
		return HttpResult.ok(System.currentTimeMillis()+"");
	}

}